home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
tex
/
dvi
/
dvieps.arc
/
CHARGF.H
< prev
next >
Wrap
Text File
|
1988-10-16
|
11KB
|
345 lines
/* -*-C-*- chargf.h */
/*-->chargf*/
/**********************************************************************/
/******************************* chargf *******************************/
/**********************************************************************/
int
chargf(c,outfcn) /* return 0 on success, and EOF on failure */
BYTE c; /* current character value */
void (*outfcn)(); /* (possibly NULL) function to output current row */
{
UNSIGN16 d; /* step in m index */
BOOLEAN do_output; /* FALSE if outfcn is NULL */
register UNSIGN16 k; /* loop step */
register INT16 m,n; /* column,row indices in image[n][m] */
long p; /* pointer into font file */
BYTE paint_switch; /* alternates between BLACK and WHITE */
struct char_entry *tcharptr;/* temporary char_entry pointer */
register BYTE the_byte; /* current command byte */
UNSIGN32 the_word; /* temporary result holder */
/* NB: We only test for equality with BLACK. WHITE is any non-zero
bit pattern, so we cannot test for equality with it */
#define BLACK ((BYTE)0)
#define WHITE ((BYTE)(!BLACK))
/*******************************************************************
This function is called to process a single character description in
the GF font file, and to set the character metrics hp, wp, xoffp,
and yoffp for it. The character description may start either at a
special (XXX) command, or at a beginning-of-character (BOC or BOC1)
command. It processes the character description up to, and
including, the end-of-character (EOC) command which terminates it.
The GF raster description is encoded in a complex form, but is
guaranteed to step across raster rows from left to right, and down
from the top row to bottom row, such that in references to
image[n][m], m never decreases in a row, and n never increases in a
character. This means that we only require enough memory space to
hold one row, provided that outfcn(c,yoff) is called each time a row
is completed. This is an important economization for
high-resolution output devices -- e.g. a 10pt character at 2400
dots/inch would require about 8Kb for the entire image, but fewer
than 25 bytes for a single row. A 72pt character (such as in the
aminch font) would need about 430Kb for the image, but only about
200 bytes for a row.
Access to bit m in the current row is controlled through the macros
SETBIT(m) and TESTBIT(m) so we need not be concerned about the
details of bit masking. Too bad C does not have a bit data type!
The row image is recorded in such a way that bits min_m .. max_m are
mapped onto bits 0 .. (max_m - min_m) in img_row[], so that
outfcn(c,yoff) should be relieved of any shifting operations.
outfcn(c,yoff) is NEVER called if either of hp or wp is <= 0, or if
if it is NULL.
*******************************************************************/
if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
{
(void)warning(
"chargf(): Character value out of range for GF font file");
return(EOF);
}
tcharptr = &(fontptr->ch[c]);
p = (long)tcharptr->fontrp; /* font file raster pointer */
if (p < 0L)
{
(void)warning(
"chargf(): Requested character not found in GF font file");
return(EOF);
}
if (FSEEK(fontfp,p,0))
{
(void)warning(
"chargf(): FSEEK() failure for GF font file character raster");
return(EOF);
}
do_output = (BOOLEAN)(outfcn != (void(*)())NULL);
(void)skgfspec(); /* skip any GF special commands */
the_byte = (BYTE)nosignex(fontfp,(BYTE)1);
if ((the_byte != GFBOC) && (the_byte != GFBOC1))
{
(void)warning(
"chargf(): GF font file not positioned at BOC or BOC1 command");
return(EOF);
}
for (;;) /* loop with exit at EOC, or at BOC or BOC1 if no rasters */
{
switch (the_byte)
{
case GFPAINT0:
paint_switch = (BYTE)(!paint_switch);
break;
case GFPAINT1:
d = (UNSIGN16)nosignex(fontfp,(BYTE)1);
if (do_output && (paint_switch == BLACK))
{
for (k = 0; k < d; (++m, ++k))
SETBIT(m);
}
else
m += (INT16)d;
paint_switch = (BYTE)(!paint_switch);
break;
case GFPAINT2:
d = (UNSIGN16)nosignex(fontfp,(BYTE)2);
if (do_output && (paint_switch == BLACK))
{
for (k = 0; k < d; (++m, ++k))
SETBIT(m);
}
else
m += (INT16)d;
paint_switch = (BYTE)(!paint_switch);
break;
case GFPAINT3: /* METAFONT never needs this */
d = (UNSIGN16)nosignex(fontfp,(BYTE)3); /* NOTE: truncation */
if (do_output && (paint_switch == BLACK))
{
for (k = 0; k < d; (++m, ++k))
SETBIT(m);
}
else
m += (INT16)d;
paint_switch = (BYTE)(!paint_switch);
break;
case GFBOC: /* beginning-of-character -- long form */
the_word = (UNSIGN32)nosignex(fontfp,(BYTE)4);
p = (long)signex(fontfp,(BYTE)4);
if ((UNSIGN32)c != the_word)
{
if (p < 0L)
{
(void)warning(
"chargf(): Requested character not found in back chain in GF font file");
return(EOF);
}
else
(void)FSEEK(fontfp,p,0); /* must follow back chain */
break;
}
else
{
min_m = (INT16)signex(fontfp,(BYTE)4);
max_m = (INT16)signex(fontfp,(BYTE)4);
min_n = (INT16)signex(fontfp,(BYTE)4);
max_n = (INT16)signex(fontfp,(BYTE)4);
}
if ((min_m < MIN_M) || (MAX_M < max_m) ||
(min_n < MIN_N) || (MAX_N < max_n))
{
(void)warning(
"chargf(): GF font file character box too large for me");
return(EOF);
}
m = min_m;
n = max_n;
paint_switch = WHITE;
img_words = (UNSIGN16)((max_m - min_m + 1 + 31) >> 5);
if (do_output)
(void)clrrow();
tcharptr->hp = (COORDINATE)(max_n - min_n + 1);
tcharptr->wp = (COORDINATE)(max_m - min_m + 1);
tcharptr->xoffp = -(COORDINATE)(min_m);
tcharptr->yoffp = (COORDINATE)(max_n);
if (!VISIBLE(tcharptr))
return(0); /* empty character raster -- nothing to output */
break;
case GFBOC1: /* beginning-of-character -- short form */
if (c != (BYTE)nosignex(fontfp,(BYTE)1))
{
(void)warning(
"chargf(): Requested character not found in GF font file");
return(EOF);
}
else
{
min_m = (INT16)nosignex(fontfp,(BYTE)1);
max_m = (INT16)nosignex(fontfp,(BYTE)1);
min_m = max_m - min_m;
min_n = (INT16)nosignex(fontfp,(BYTE)1);
max_n = (INT16)nosignex(fontfp,(BYTE)1);
min_n = max_n - min_n;
}
if ((min_m < MIN_M) || (MAX_M < max_m) ||
(min_n < MIN_N) || (MAX_N < max_n))
{
(void)warning(
"chargf(): GF font file character box too large for me");
return(EOF);
}
m = min_m;
n = max_n;
paint_switch = WHITE;
img_words = (UNSIGN16)((max_m - min_m + 1 + 31) >> 5);
if (do_output)
(void)clrrow();
tcharptr->hp = (COORDINATE)(max_n - min_n + 1);
tcharptr->wp = (COORDINATE)(max_m - min_m + 1);
tcharptr->xoffp = -(COORDINATE)(min_m);
tcharptr->yoffp = (COORDINATE)(max_n);
if (!VISIBLE(tcharptr))
return(0);/* empty character raster -- nothing to output */
break;
case GFEOC: /* end-of-character */
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
--n; /* advance to next row below */
for ( ; n >= min_n ; --n) /* output any remaining rows */
(void)(*outfcn)(c,max_n-n);
}
return(0); /* exit outer loop */
case GFSKIP0:
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
}
--n; /* advance to next row below */
m = min_m;
paint_switch = WHITE;
break;
case GFSKIP1:
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */